package com.aliasi.annotate.corpora;
  
import com.aliasi.chunk.BioTagChunkCodec;
import com.aliasi.chunk.Chunk;  
import com.aliasi.chunk.Chunking;  
import com.aliasi.tokenizer.Tokenizer;  
import com.aliasi.tokenizer.TokenizerFactory;  
import com.aliasi.util.Strings;  
import java.util.Arrays;  
import java.util.ArrayList;  
import java.util.Set;  

public class ChunkHandlerAdapter {  
  
    /** 
     * Returns the array of tags for the specified chunking, relative 
     * to the specified tokenizer factory. 
     * 
     * @param chunking Chunking to convert to tags. 
     * @param factory Tokenizer factory for token generation. 
     */  
    public static String[] toTags(Chunking chunking,  
                                  TokenizerFactory factory) {  
        CharSequence cSeq = chunking.charSequence();  
        char[] cs = Strings.toCharArray(cSeq);
        Set chunkSet = chunking.chunkSet();  
        Chunk[] chunks = new Chunk[chunkSet.size()];  
        chunkSet.toArray(chunks);  
        Arrays.sort(chunks,Chunk.TEXT_ORDER_COMPARATOR);  
        ArrayList tokenList = new ArrayList();  
        ArrayList whiteList = new ArrayList();  
        ArrayList tagList = new ArrayList();  
        int pos = 0;  
        for (Chunk nextChunk : chunks) {  
            String type = nextChunk.type();  
            int start = nextChunk.start();  
            int end = nextChunk.end();  
            outTag(cs,pos,start,tokenList,whiteList,tagList,factory);  
            chunkTag(cs,start,end,type,tokenList,whiteList,tagList,factory);  
            pos = end;  
        }  
        outTag(cs,pos,cSeq.length(),tokenList,whiteList,tagList,factory);
        String[] tags = new String[tagList.size()];  
        tagList.toArray(tags);  
        return tags;  
    }  
  
    /** 
     * Returns <code>true</code> if the specified tokens and 
     * whitespaces are consistent with the specified tokenizer 
     * factory.  A tokenizer is consistent with the specified 
     * tokens and whitespaces if running the tokenizer over 
     * the concatenation of the tokens and whitespaces produces 
     * the same tokens and whitespaces. 
     * 
     * @param toks Tokens to check. 
     * @param whitespaces Whitespaces to check. 
     * @param tokenizerFactory Factory to create tokenizers. 
     * @return <code>true</code> if the tokenizer is consistent with 
     * the tokens and whitespaces. 
     */  
    public static boolean consistentTokens(String[] toks,  
                                           String[] whitespaces,  
                                           TokenizerFactory tokenizerFactory) {  
        if (toks.length+1 != whitespaces.length) return false;  
        char[] cs = getChars(toks,whitespaces);  
        Tokenizer tokenizer = tokenizerFactory.tokenizer(cs,0,cs.length);  
        String nextWhitespace = tokenizer.nextWhitespace();  
        if (!whitespaces[0].equals(nextWhitespace)) {  
            return false;  
        }  
        for (int i = 0; i < toks.length; ++i) {  
            String token = tokenizer.nextToken();  
            if (token == null) {  
                return false;  
            }  
            if (!toks[i].equals(token)) {  
                return false;  
            }  
            nextWhitespace = tokenizer.nextWhitespace();  
            if (!whitespaces[i+1].equals(nextWhitespace)) {  
                return false;  
            }  
        }  
        return true;  
    }  
  
    static void outTag(char[] cs, int start, int end,  
                       ArrayList tokenList, ArrayList whiteList, ArrayList tagList,  
                       TokenizerFactory factory) {  
        Tokenizer tokenizer = factory.tokenizer(cs,start,end-start);  
        whiteList.add(tokenizer.nextWhitespace());  
        String nextToken;  
        while ((nextToken = tokenizer.nextToken()) != null) {  
            tokenList.add(nextToken);  
            tagList.add(BioTagChunkCodec.OUT_TAG);  
            whiteList.add(tokenizer.nextWhitespace());  
        }  
  
    }  
  
    static void chunkTag(char[] cs, int start, int end, String type,  
                         ArrayList tokenList, ArrayList whiteList, ArrayList tagList,  
                         TokenizerFactory factory) {  
        Tokenizer tokenizer = factory.tokenizer(cs,start,end-start);  
        String firstToken = tokenizer.nextToken();  
        tokenList.add(firstToken);  
        tagList.add(BioTagChunkCodec.BEGIN_TAG_PREFIX + type);  
        while (true) {  
            String nextWhitespace = tokenizer.nextWhitespace();  
            String nextToken = tokenizer.nextToken();  
            if (nextToken == null) break;  
            tokenList.add(nextToken);  
            whiteList.add(nextWhitespace);  
            tagList.add(BioTagChunkCodec.IN_TAG_PREFIX + type);  
        }  
    }
  
    static char[] getChars(String[] toks, String[] whitespaces) {  
        StringBuffer sb = new StringBuffer();  
        for (int i = 0; i < toks.length; ++i) {  
            sb.append(whitespaces[i]);  
            sb.append(toks[i]);  
        }  
        sb.append(whitespaces[whitespaces.length-1]);  
        return Strings.toCharArray(sb);  
    }  
  
} 
